function compileList(self)
{
    self.List = Class.create(
    {
    	/**
    	 * Row HTML.
    	 */
    	ROW_HTML: '<tr class="ROW_CLASS">COLUMNS</tr>',
    	
    	/**
    	 * Colummn HTML.
    	 */
    	COLUMN_HTML: '<td class="COLUMN_CLASS"><div class="COLUMN_CLASS">DATA</div></td>',
    	
        /**
         * Constructor.
         * 
         * @param listDiv The div to hold the list.
         * @param rowClass The name of the main row class.
         * @param rowAlternateClass The name of the alternate row class.
         * @param columnClasses Array of column classes.
         * @param Any function to call on result select.
         */
         initialize: function(listDiv, rowClass, rowAlternateClass, columnClasses, resultSelectCallback)
         {
         	// Setup the array that will hold the list data.
         	this.data = new Array();
         	this.callbackData = new Array();
         	
         	// Store parameters.
         	this.listDiv = listDiv;
         	this.rowClass = rowClass;
         	this.rowAlternateClass = rowAlternateClass;
         	this.columnClasses = columnClasses;
         	this.resultSelectCallback = resultSelectCallback;
         	
         	// Insert table and get a reference to it.
         	this.tableBody = this.listDiv.contents().contents();
         },
         
         /**
          * Appends row data to the list.
          * 
          * @param rowData The row data to append.
          * @param callbackData Any callback data.
          */
         appendRow: function(rowData, callbackData)
         {
         	this.data[this.data.length] = rowData;
         	if (callbackData)
         	{
         		this.callbackData[this.callbackData.length] = callbackData;
         	}
         	
         	// Update HTML.
            this.buildList(this.data.length-1);
         },
         
         /**
          * Inserts row data into the list.
          * 
          * @param rowData the row data to insert.
          * @param callbackData Any callback data.
          * @param index The index to insert the row data.
          */
         insertRow: function(rowData, callbackData, index)
         {
         	if (index < this.data.length)
         	{
         	  // Move existing data rows down.
         	  for (var i = this.data.length; i > index; i--)
         	  {
         	  	this.data[i] = this.data[i-1];
         	  	if (callbackData)
         	  	{
         	  	   this.callbackData[i] = this.callbackData[i-1];
         	  	}
         	  }
         	  
         	  // Insert new data row.
         	  this.data[index] = rowData;
         	  if (callbackData)
         	  {
         	      this.callbackData[index] = callbackData;
         	  }
         	}
         	
         	// Update HTML.
         	this.buildList(index);
         },
         
         /**
          * Clears the list.
          */
         clear: function()
         {
         	this.data.clear();
         	this.callbackData.clear();
         	this.tableBody.empty();
         },
         
         /**
          * Builds the list HTML.
          *
          * @param rowInsertedIndex The index of the last updated row.
          */
         buildList: function(rowInsertedIndex)
         {
         	// Iterate through all the data.
         	var index = 0;
         	var isAlternate = false;
         	
     		// Detemine initial alternate status.
     		isAlternate = rowInsertedIndex%2 != 0;    // Odd indexes are alternate rows.

     		// Get any existing rows.
     		var numChidren = this.tableBody.children().length;

     		// Update existing rows from the inserted index.
     		for (index = rowInsertedIndex; index < numChidren; index++)
     		{
     			// Update row.
     			var row = this.tableBody.children(':eq(' + index + ')');
     			row = row.replaceWith(this.makeRowHtml(this.data[index], isAlternate)).children(':eq(' + index + ')');;
     			this.addCallback(row, index);
                
                // Update alternate status.
                isAlternate = !isAlternate;
     		}
     		
     		// Append any new rows.
     		while (index < this.data.length)
     		{
     			// Append row.
     			var rowHtml = this.makeRowHtml(this.data[index], isAlternate);
     			var row = this.tableBody.append(rowHtml).children(':eq(' + index + ')');
     			this.addCallback(row, index);

     			// Update alternate status.
                isAlternate = !isAlternate;
                
                // Move to next row.
                index++;
     		}
         },
         
         /**
          * Adds callback to the specified row element with the data index.
          * 
          * @param row Row to add callback to.
          * @param index The index of the data.
          */
         addCallback: function(row, index)
         {
         	if (Object.isFunction(this.resultSelectCallback) && index < this.callbackData.length)
            {
                row.click(
                   function(self, data)
                   {
                       return function()
                       {
                           self.resultSelectCallback(data);
                       }
                   }(this, this.callbackData[index]));
            }
         },
         
         /**
          * Makes the row HTML.
          * 
          * @param rowData The row data.
          * @param isAlternate Whether or not this is an alternate row.
          * 
          * @return The row HTML.
          */
         makeRowHtml: function(rowData, isAlternate)
         {
         	// Construct columns.
         	var columnsHtml = "";
         	for (var index = 0; index < rowData.length; index++)
         	{
         		columnsHtml += this.makeColumnHtml(rowData, index);
         	}

         	// Construct row.
         	var rowClass = isAlternate ? this.rowAlternateClass : this.rowClass;
         	return this.ROW_HTML.replace(/ROW_CLASS/, rowClass)
         	  .replace(/COLUMNS/, columnsHtml);
         },
         
         /**
          * Makes the column HTML.
          * 
          * @param rowData The row data.
          * @param index The column index.
          * 
          * @return The column HTML.
          */
         makeColumnHtml: function(rowData, index)
         {
         	return this.COLUMN_HTML.replace(/COLUMN_CLASS/g, this.columnClasses[index])
         	  .replace(/DATA/, rowData[index]);
         }
    });
}